package com.changgou.search.service.impl;

import com.alibaba.fastjson.JSON;
import com.changgou.goods.feign.SkuFeign;
import com.changgou.goods.pojo.Sku;
import com.changgou.search.dao.SkuEsMapper;
import com.changgou.search.pojo.SkuInfo;
import com.changgou.search.service.SkuService;
import entity.Result;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.terms.StringTerms;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.*;

/**
 * 描述
 *
 * @author www.itheima.com
 * @version 1.0
 * @package com.changgou.search.service.impl *
 * @since 1.0
 */
@Service
public class SkuServiceImpl implements SkuService {


    @Autowired
    private SkuFeign skuFeign;

    @Autowired
    private SkuEsMapper skuEsMapper;

    @Autowired
    private ElasticsearchTemplate elasticsearchTemplate;


    @Override
    public void importEs() {
        //1.调用 goods微服务的fegin 查询 符合条件的sku的数据
        Result<List<Sku>> skuResult = skuFeign.findByStatus("1");
        List<Sku> data = skuResult.getData();//sku的列表
        //将sku的列表 转换成es中的skuinfo的列表
        List<SkuInfo> skuInfos = JSON.parseArray(JSON.toJSONString(data), SkuInfo.class);
        for (SkuInfo skuInfo : skuInfos) {
            //获取规格的数据  {"电视音响效果":"立体声","电视屏幕尺寸":"20英寸","尺码":"165"}

            //转成MAP  key: 规格的名称  value:规格的选项的值
            Map<String, Object> map = JSON.parseObject(skuInfo.getSpec(), Map.class);
            skuInfo.setSpecMap(map);
        }


        // 2.调用spring data elasticsearch的API 导入到ES中
        skuEsMapper.saveAll(skuInfos);
    }


    @Override
    public Map search(Map<String, String> searchMap) {
        String keywords="";
        if(searchMap!=null){
            //获取关键字值
            keywords = searchMap.get("keywords");
            if(StringUtils.isEmpty(keywords)){
                keywords = "华为"; //赋值一个默认值
            }
        }else {
            keywords = "华为"; //赋值一个默认值
        }


        //创建查询对象 的构建对象
        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();

        //设置分组条件 商品分类
        nativeSearchQueryBuilder.addAggregation(AggregationBuilders.terms("skuCategorygroup").
                field("categoryName").size(50));

        //设置分组条件  商品品牌 **
        nativeSearchQueryBuilder.addAggregation(AggregationBuilders.terms("skuBrandgroup").
                field("brandName").size(50));

        //设置分组条件 商品的规格
        nativeSearchQueryBuilder.addAggregation(AggregationBuilders.terms("skuSpecgroup").
                field("spec.keyword").size(100));


        //设置主关键字查询
        nativeSearchQueryBuilder.withQuery(QueryBuilders.matchQuery("name",keywords));

        //组合查询
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        if(!StringUtils.isEmpty(searchMap.get("brand"))){
            boolQueryBuilder.filter(QueryBuilders.termQuery("brandName",searchMap.get("brand")));
        }

        if (!StringUtils.isEmpty(searchMap.get("category"))){
            boolQueryBuilder.filter(QueryBuilders.termQuery("categoryName",
                    searchMap.get("category")));
        }
        if(searchMap!=null){
            for (String key:searchMap.keySet()){
                if(key.startsWith("spec_")){
                    boolQueryBuilder.filter(QueryBuilders.
                            termQuery("specMap."+key.substring(5)+".keyword",searchMap.get(key)));
                }
            }

            String price = searchMap.get("price");
            if(!StringUtils.isEmpty(price)){
                String[] split = price.split("-");
                if(!split[1].equalsIgnoreCase("*")){
                    boolQueryBuilder.filter(QueryBuilders.
                            rangeQuery("price").
                            from(split[0],true).to(split[1],true));
                }else {
                    boolQueryBuilder.filter(QueryBuilders.
                            rangeQuery("price").gte(split[0]));
                }
            }

        }





        //构建过滤查询
        nativeSearchQueryBuilder.withFilter(boolQueryBuilder);

        //构建分页查询
        Integer pageNum = 1;
        if(!StringUtils.isEmpty(searchMap.get("pageNum"))){
            try{
                pageNum = Integer.valueOf(searchMap.get("pageNum"));
            }catch (NumberFormatException e){
                e.printStackTrace();
                pageNum=1;
            }
        }

        Integer pageSize = 30;
        nativeSearchQueryBuilder.withPageable(PageRequest.of(pageNum - 1, pageSize));

        //构建排序插查询
        String sortRule = searchMap.get("sortRule");
        String sortField = searchMap.get("sortField");
        if(!StringUtils.isEmpty(sortRule) && !StringUtils.isEmpty(sortField)){
            nativeSearchQueryBuilder.withSort(SortBuilders.fieldSort(sortField).
                    order(sortRule.equals("DESC")? SortOrder.DESC:SortOrder.ASC));
        }

        //设置高亮条件
        nativeSearchQueryBuilder.withHighlightFields(new HighlightBuilder.Field("name"));
        nativeSearchQueryBuilder.withHighlightBuilder(new HighlightBuilder().
                preTags("<em style=\"color:red\">").postTags("</em>"));
        //设置主关键字查询
        nativeSearchQueryBuilder.withQuery(QueryBuilders.multiMatchQuery(keywords,"name",
                "brandName","categoryName"));


        //构建查询对象
        NativeSearchQuery query = nativeSearchQueryBuilder.build();

        //执行查询
        AggregatedPage<SkuInfo> skuPage = elasticsearchTemplate.queryForPage(query, SkuInfo.class,
                new SearchResultMapperImpl());

        //获取分组结果
        StringTerms stringTerms = (StringTerms) skuPage.getAggregation("skuCategorygroup");
        //获取商品品牌分组结果
        StringTerms StringTermsByBrand = (StringTerms)skuPage.getAggregation("skuBrandgroup");
        //获取商品规格
        StringTerms skuSpecgroup = (StringTerms) skuPage.getAggregation("skuSpecgroup");

        List<String> categoryList = this.getStringsCategoryList(stringTerms);
        List<String> brandList = this.getStringsBrandList(StringTermsByBrand);
        Map<String, Set<String>> specMap =  this.getStringSetMap(skuSpecgroup);

        //返回结果
        Map result = new HashMap<>();
        result.put("categoryList",categoryList);
        result.put("specMap",specMap);
        result.put("brandList",brandList);
        result.put("rows",skuPage.getContent());
        result.put("total",skuPage.getTotalElements());
        result.put("totalPages",skuPage.getTotalPages());
        return result;
    }

    /**
     * 获取商品规格
     * @param skuSpecgroup
     * @return
     */
    private Map<String, Set<String>> getStringSetMap(StringTerms skuSpecgroup) {
        HashMap<String, Set<String>> specMap = new HashMap<>();
        HashSet<String> specList = new HashSet<>();
        if(skuSpecgroup!=null){
            for (StringTerms.Bucket bucket : skuSpecgroup.getBuckets()) {
                System.out.printf("bucket.getKeyAsString():=-="+bucket.getKeyAsString());
                specList.add(bucket.getKeyAsString());
            }
        }

        for (String specJson : specList) {
            System.out.printf("specJson"+specJson);
            Map<String,String> map = JSON.parseObject(specJson, Map.class);
            for (Map.Entry<String, String> entry : map.entrySet()) {
                System.out.printf("entry==="+entry);
                String key = entry.getKey();//规格名字 
                String value = entry.getValue();//规格选项值
                //获取当前回个名字对应的规格数据
                Set<String> specValues = specMap.get(key);
                if(specValues == null){
                    specValues = new HashSet<String>();
                }
                //将当前规格加入到集合中
                specValues.add(value);
                //将数据存入到specMap中
                specMap.put(key,specValues);
                
            }
        }
        return specMap;
    }

    /**
     * brand
     * @param stringTermsByBrand
     * @return
     */
    private List<String> getStringsBrandList(StringTerms stringTermsByBrand) {
        List<String> brandList = new ArrayList<String>();
        if(stringTermsByBrand != null){
            for (StringTerms.Bucket bucket : stringTermsByBrand.getBuckets()) {
                String keyAsString = bucket.getKeyAsString();//分组的值
                System.out.printf("分组的值====:"+keyAsString);
                brandList.add(keyAsString);
            }
            System.out.printf(brandList.toString());
        }
        return brandList;
    }

    /**
     * 获取分类列表数据
     * @param stringTerms
     * @return
     */
    public List<String> getStringsCategoryList(StringTerms stringTerms){
        List<String> categoryList = new ArrayList<String>();
        if(stringTerms != null){
            for (StringTerms.Bucket bucket : stringTerms.getBuckets()) {
                String keyAsString = bucket.getKeyAsString();//分组的值
                System.out.printf("分组的值====:"+keyAsString);
                categoryList.add(keyAsString);
            }
            System.out.printf(categoryList.toString());
        }
        return categoryList;
    }




}
